1. Field of the Invention
The present invention relates generally to data processing and, more particularly, to inlining into a caller method.
2. Description of the Related Art
Inlining is a method of improving program performance by embedding the body of a callee into the body of its caller. The performance improvement is gained by eliminating the overhead of an invocation and exposing additional optimization opportunities in the combined code. One of the fundamental elements of the Java™ programming language is its object-oriented class hierarchy (JAVA and all JAVA-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both). Therefore, a method implementation in a class, A, can be overridden by an implementation of the same method in a subclass of A. A method that can be overridden is called a “virtual method.”
When there is more than one implementation of a callee, any of the implementations can be called, or even all of them at different executions of the call. This makes inlining of virtual methods challenging in terms of trying to improve performance and preserving correctness. In other words, it is important to inline the “right” method, or the method that is “right” the majority of the time, but always execute the correct implementation for the call. If the right implementation is not inlined, then the code will have to make an invocation, which slows down execution; therefore, it is important to be right more often to achieve the desired performance gain.
One existing solution to inlining virtual methods is to limit inlining to cases where the callee is not overridden at the time the caller gets compiled, using an “override guard” for correctness. An “override guard” is a relatively inexpensive test that checks whether a method implementation got overridden. Information identifying whether a method is overridden gets updated in the Java virtual machine when a class with an overriding implementation gets loaded. In an object-oriented class hierarchy, where method overriding is common, this limitation is too strict. For example, there are cases where the same implementation will always be called at a particular call-point and still will not be inlined, simply because another implementation of that method exists.
Another existing solution is to use profiling information to choose which method to inline and to inline it using a “virtual guard.” A “virtual guard” is more expensive than an “override guard,” but allows the caller to keep using the inlined implementation, even if it got overridden, as long as it can verify that this is the appropriate implementation. Using profiling information can be quite expensive in terms of memory usage and performance, because it requires collecting and keeping profiling data for every call edge in the call-graph.
Yet another existing solution inlines when the callee is not overridden at the time the caller gets compiled without using an “override guard.” This method requires re-compiling the caller (using “on stack replacement” when needed) for correctness when an overriding implementation of the callee gets loaded. The advantage of this method is that there is no need for a “virtual guard” when there are no additional implementations of the method, which may improve performance over the “virtual guard” solution. On the other hand, this method requires a decompile and recompile whenever a class with an overriding method gets loaded.